//---------------------------------------------------------------------------

#include "Iec104.h"

//---------------------------------------------------------------------------
int IEC104_CheckPkgType(uint8_t *pApdu)
{
    APCI_t *pApci=(APCI_t *)pApdu;
    if(pApci->SOM!=0x68)
        return 0;
    if(pApci->CCM.U_CCM.U.MsgType==0x03)
        return U_PKG;
    if(pApci->CCM.U_CCM.U.MsgType==0x01)
        return S_PKG;
    if((pApci->CCM.U_CCM.U.MsgType&0x01)==0)
        return I_PKG;
    return 0;
}
uint8_t IEC104_ChkIPkgAsduType(uint8_t *pApdu)
{
	struct APDU_t   *pAp=(struct APDU_t *)pApdu;
	struct ASDU_t *pAsdu=(struct ASDU_t *)pAp->Asdu;
	return pAsdu->TYP;
}
/*可处理总召唤
pApdu  接收到的I帧
pRespone   回复的I帧
pSendCNT  返回的发送序号
pRecCNT     接收序号
bAct            判断是否发送停止信号
times          对同一个I帧的处理信号
*/
int IEC104_IPkgResponeAct(uint8_t *pApdu,uint8_t *pRespone,uint16_t *pSendCNT,uint16_t *pRecCNT,bool bAct)//未改变pApdu的值
{
	int iLen=0;
	struct APDU_t   *pAp=(struct APDU_t *)pApdu;
	printf("	*****pAp->APCI.CCM.I_CCM.NS1=  NR1=%d=%d\r\n",pAp->APCI.CCM.I_CCM.NS,pAp->APCI.CCM.I_CCM.NR);
	struct ASDU_t *pAsdu=(struct ASDU_t *)pAp->Asdu;
	struct APDU_t *pApduResp;
	struct ASDU_t *pAsduResp;
	iLen=pAp->APCI.APDU_LEN;
	memcpy(pRespone,pApdu,iLen+2);
	pApduResp=(struct APDU_t *)pRespone;
	*pSendCNT=pAp->APCI.CCM.I_CCM.NR;    //主站接收序号,从站发送序号
	*pRecCNT=pAp->APCI.CCM.I_CCM.NS; //从站接收序号,主站发送序号
	printf("	*****pAp->APCI.CCM.I_CCM.NS2 =  %dNR2 =%d\r\n",pAp->APCI.CCM.I_CCM.NS,pAp->APCI.CCM.I_CCM.NR);
	pApduResp->APCI.CCM.I_CCM.NS=*pSendCNT;
	pApduResp->APCI.CCM.I_CCM.NR=*pRecCNT+0x02; //主站接收+1即从站发送了一次

	pAsduResp=(struct ASDU_t *)pApduResp->Asdu;
	if(bAct)
	{
		if(pAsdu->COT[0].all=0x06)
		{
			pAsduResp->COT[0].all=0x07;//激活确认
			return  iLen+2;
		}
		else if(pAsdu->COT[0].all=0x08)
		{
			pAsduResp->COT[0].all=0x09;//停止激活确认
			return iLen+2;
		}
			else
				return 0;
	}
	else
	{
		if(pAsdu->COT[0].all==0x06)
		{
			pAsduResp->COT[0].all=0x0a;//激活结束
			return  iLen+2;
		}
		return 0;
	}
	
	return 0;
}
/*int IEC104_IPkgRespone(uint8_t *pApdu,uint8_t *pRespone,uint16_t *pSendCNT,uint16_t *pRecCNT,uint8_t *pData,uint8_t iLen)
	 {
	  struct APDU_t   *pAp=(struct APDU_t *)pApdu;
	 // struct ASDU_t *pAsdu=(struct ASDU_t *)pAp->Asdu;
	  struct APDU_t *pApduResp;
	  struct ASDU_t *pAsduResp;
	  pApduResp=(struct APDU_t *)pRespone;
      *pRecCNT=pAp->APCI.CCM.I_CCM.NR;
	  *pSendCNT=pAp->APCI.CCM.I_CCM.NS;
	  pApduResp->APCI.SOM=0x68;
	  pApduResp->APCI.CCM.I_CCM.NS=pAp->APCI.CCM.I_CCM.NR;
	  pApduResp->APCI.CCM.I_CCM.NR=pAp->APCI.CCM.I_CCM.NS+0x02;
	  memcpy(pApduResp->Asdu,pData,iLen);
	  pApduResp->APCI.APDU_LEN=iLen+4;
	  return  iLen+6;
	 } */


int IEC104_UPkgRespone(uint8_t *pApdu,uint8_t *pRespone)
{
    APCI_t *pApci=(APCI_t *)pApdu;
    if(pApci->CCM.U_CCM.U.StartDt==0x01)
    {
        pApci->CCM.U_CCM.U.StartDt=0x02;
        memcpy(pRespone,pApdu,6);
        return 1;
    }
    if(pApci->CCM.U_CCM.U.StopDt==0x01)
    {
        pApci->CCM.U_CCM.U.StopDt=0x02;
        memcpy(pRespone,pApdu,6);
        return 2;
    }
    if(pApci->CCM.U_CCM.U.TestFR==0x01)
    {
        pApci->CCM.U_CCM.U.TestFR=0x02;
        memcpy(pRespone,pApdu,6);
        return 3;
    }
    return 0;
}

int  IEC104_SPkgRespone(uint8_t *pRespone,uint16_t *pSendCNT)
{
    struct  APCI_t *pAPCI=(struct  APCI_t *)pRespone;
    *pSendCNT=pAPCI->CCM.S_CCM.NR;
    return 0;
}



/*int  IEC104_IPkg(uint8_t *pApdu,uint8_t *pAsdu,int AsduLen,uint16_t SendCNT,uint16_t RecCNT)
	  {
		struct  APCI_t *pAPCI=(struct  APCI_t *)pApdu;
		pAPCI->SOM=68;
		pAPCI->APDU_LEN=AsduLen+4;
		pAPCI->CCM.I_CCM.NS=SendCNT;
		pAPCI->CCM.I_CCM.NS<<=1;
		pAPCI->CCM.I_CCM.NR=RecCNT;
		pAPCI->CCM.I_CCM.NR<<=1;
		struct APDU_t *pAPDU=(struct APDU_t *)pApdu;
		memcpy(pAPDU->Asdu,pAsdu,AsduLen);
		return  pAPCI->APDU_LEN+2;
	  }    */

void IEC104_GetLocalTime(uint8_t *pTime)
{
	uint16_t mSecond;

	struct timeval tv;
    gettimeofday(&tv,NULL);
	time_t time3;
	struct tm *p;
	time3 = time(NULL);
	p = localtime(&time3);
	printf("%04d-%02d-%02d %02d-%02d-%02d-%02d\r\n", (1900 + p->tm_year), ( 1 + p->tm_mon), p->tm_mday,
				p->tm_hour, p->tm_min, p->tm_sec,tv.tv_usec/1000);
	CP56time2a *pCP56time2a=(CP56time2a *)pTime;
	pCP56time2a->msec[0]=tv.tv_usec/1000;
	pCP56time2a->msec[1]=p->tm_sec;
	pCP56time2a->min=p->tm_min;
	pCP56time2a->hour=p->tm_hour;
	pCP56time2a->mday=p->tm_mday;
	pCP56time2a->wday=p->tm_mday;
	pCP56time2a->month=( 1 + p->tm_mon);
	pCP56time2a->year=(1900 + p->tm_year)-80;
	pCP56time2a->res1=0;
	pCP56time2a->res2=0;
	pCP56time2a->res3=0;
	pCP56time2a->res4=0;
	pCP56time2a->iv=0;
	pCP56time2a->su=0;
}


uint8_t mydata2[4] = {2,0,0,4};
uint8_t mydata3[4] = {3,0,0,4};
uint8_t mydata4[4] = {4,0,0,4};
/*
pApdu	接受到的主机数据，
pRespone   要发给主机的数据，
TYP   传输类型
COT  传输原因
YXdata   要发的YX数据，
YXdata_num YX数据个数
RTUaddrs  公共地址，即RTU地址
*/
int IEC104_SendYX(uint8_t *pApdu,uint8_t *pRespone,uint8_t  TYP,uint8_t COT,uint8_t* YXdata,int YXdata_num,int RTUaddrs)//遥信数据
{
	int iLen=0;
	int YX_size = 0;
	switch(TYP)
	{
		case TYP_Telesignaling_01:
		{
			YX_size = 1;
			break;
		}
		case TYP_Telesignaling_03:
		{
			YX_size = 1;
			break;
		}
		case TYP_Telesignaling_14:
		{
			YX_size =8;
			break;
		}
		case TYP_SOE_02:
		{
			YX_size =4;
			break;
		}
		case TYP_SOE_04:
		{
			YX_size =4;
			break;
		}
		case TYP_SOE_1e:
		{
			YX_size =8;
			break;
		}
		case TYP_SOE_1f:
		{
			YX_size =8;
			break;
		}
	}

	struct APDU_t   *pAp=(struct APDU_t *)pApdu;
	struct ASDU_t *pAsduResp;
	struct APDU_t *pApduResp;

	iLen=pAp->APCI.APDU_LEN;
	memcpy(pRespone,pApdu,iLen+2);
	pApduResp=(struct APDU_t *)pRespone;

	pApduResp->APCI.CCM.I_CCM.NS=pAp->APCI.CCM.I_CCM.NR;    //主站接收序号,从站发送序号
	pApduResp->APCI.CCM.I_CCM.NR=pAp->APCI.CCM.I_CCM.NS+0x02; //从站接收序号,主站发送序号

	pApduResp->APCI.APDU_LEN = 0x0a+YX_size*YXdata_num;
	iLen=pApduResp->APCI.APDU_LEN;
	pAsduResp=(struct ASDU_t *)pApduResp->Asdu;
	pAsduResp->TYP = TYP;//单点遥信
	pAsduResp->VSQ.all = YXdata_num; //信息元素个数

	pAsduResp->COT[0].all =  COT;//传送原因,响应总召唤


	pAsduResp->CommAdr[0] = RTUaddrs;//公共地址，即RTU地址
	pAsduResp->CommAdr[1] = 0;
	memcpy(pAsduResp->MsgAdr,YXdata,YXdata_num*YX_size);
	iLen = iLen+2;
	return iLen;
}
int IEC104_SendYC(uint8_t *pApdu,uint8_t *pRespone,uint8_t  TYP,uint8_t COT,uint8_t* YXdata,int YXdata_num,int RTUaddrs)//遥测数据
{
	int iLen=0;
	int YC_size = 0;
	struct APDU_t   *pAp=(struct APDU_t *)pApdu;

	switch(TYP)
	{
		case TYP_Telemetry_09:
					YC_size = 3;
					break;
		case TYP_Telemetry_0a:
					YC_size = 6;
					break;
		case TYP_Telemetry_0b:
					YC_size =3;
					break;
		case TYP_Telemetry_0c:
					YC_size =6;
					break;
		case TYP_Telemetry_0d:
					YC_size =5;
					break;
		case TYP_Telemetry_0e:
					YC_size =8;
					break;
		case TYP_Telemetry_15:
					YC_size =2;
					break;
	}

	struct ASDU_t *pAsduResp;
	struct APDU_t *pApduResp;

	iLen=pAp->APCI.APDU_LEN;
	memcpy(pRespone,pApdu,iLen+2);
	pApduResp=(struct APDU_t *)pRespone;

	pApduResp->APCI.CCM.I_CCM.NS=pAp->APCI.CCM.I_CCM.NR;    //主站接收序号,从站发送序号
	pApduResp->APCI.CCM.I_CCM.NR=pAp->APCI.CCM.I_CCM.NS+0x02; //从站接收序号,主站发送序号
	// printf("	*****pAp->APCI.CCM.I_CCM.NS2 =  %dNR2 =%d\r\n",pAp->APCI.CCM.I_CCM.NS,pAp->APCI.CCM.I_CCM.NR);
	pApduResp->APCI.APDU_LEN = 0x0a+YC_size*YXdata_num;
	iLen=pApduResp->APCI.APDU_LEN;
	pAsduResp=(struct ASDU_t *)pApduResp->Asdu;
	pAsduResp->TYP = TYP;//带品质描述的测量值，每个遥测值占3个字节
	pAsduResp->VSQ.all = YXdata_num; //信息元素个数
	pAsduResp->COT[0].all =  COT;//传送原因,响应总召唤


	pAsduResp->CommAdr[0] = RTUaddrs;//公共地址，即RTU地址
	pAsduResp->CommAdr[1] = 0;
	memcpy(pAsduResp->MsgAdr,YXdata,YXdata_num*YC_size);


	iLen = iLen+2;
	return iLen;
}

int IEC104_SendKWH(uint8_t *pApdu,uint8_t *pRespone,uint8_t  TYP,uint8_t COT,uint8_t* YXdata,int YXdata_num,int RTUaddrs)//电力数据
{
	int iLen=0;
	int KWH_size = 0;
	struct APDU_t   *pAp=(struct APDU_t *)pApdu;

	switch(TYP)
	{
		case TYP_KWH_0f:
		{
			KWH_size =5;
			break;
		}
		case TYP_KWH_10:
		{
			KWH_size =8;
			break;
		}
		case TYP_KWH_25:
		{
			KWH_size =12;
			break;
		}
	}

	struct ASDU_t *pAsduResp;
	struct APDU_t *pApduResp;

	iLen=pAp->APCI.APDU_LEN;
	memcpy(pRespone,pApdu,iLen+2);
	pApduResp=(struct APDU_t *)pRespone;

	pApduResp->APCI.CCM.I_CCM.NS=pAp->APCI.CCM.I_CCM.NR;    //主站接收序号,从站发送序号
	pApduResp->APCI.CCM.I_CCM.NR=pAp->APCI.CCM.I_CCM.NS+0x02; //从站接收序号,主站发送序号
	// printf("	*****pAp->APCI.CCM.I_CCM.NS2 =  %dNR2 =%d\r\n",pAp->APCI.CCM.I_CCM.NS,pAp->APCI.CCM.I_CCM.NR);
	pApduResp->APCI.APDU_LEN = 0x0a+KWH_size*YXdata_num;
	iLen=pApduResp->APCI.APDU_LEN;
	pAsduResp=(struct ASDU_t *)pApduResp->Asdu;
	pAsduResp->TYP = TYP;//带品质描述的测量值，每个遥测值占3个字节
	pAsduResp->VSQ.all = YXdata_num; //信息元素个数
	pAsduResp->COT[0].all =  COT;//传送原因,响应总召唤


	pAsduResp->CommAdr[0] = RTUaddrs;//公共地址，即RTU地址
	pAsduResp->CommAdr[1] = 0;
	memcpy(pAsduResp->MsgAdr,YXdata,YXdata_num*KWH_size);


	iLen = iLen+2;
	return iLen;	
}
